Phần mềm vẽ đồ thị C#
6.567 lượt xem;
- Expression.cs
- project /
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace VietGraph
6 {
7 public class Expression : IEvaluatable
8 {
9 string text = "";
10 string textInternal = "";
11 bool isValid = false;
12 char charX = 'x';
13 System.Collections.Generic.Dictionary<string, double> constants;
14
15 public Expression(string expressionText)
16 {
17 this.constants = new Dictionary<string, double>();
18 this.constants.Add("pi", Math.PI);
19 this.constants.Add("e", Math.E);
20 this.ExpressionText = expressionText;
21 }
22
23 #region Public Properties for IEvaluatable
24
25
26 public string ExpressionText
27 {
28 get
29 {
30 return this.text;
31 }
32 set
33 {
34 this.text = value;
35 this.textInternal = "(" + value + ")";
36 this.textInternal = InsertPrecedenceBrackets().Trim();
37 this.Validate();
38 }
39 }
40
41 public bool IsValid
42 {
43 get
44 {
45 return this.isValid;
46 }
47 }
48 #endregion
49
50 #region Public Methods for IEvaluatable
51
52 public double Evaluate(double dvalueX)
53 {
54 if (this.isValid == false)
55 return Double.NaN;
56 int temp;
57 return EvaluateInternal(dvalueX, 0, out temp);
58 }
59
60 #endregion
61
62 #region Private Methods
63
64 private void Validate()
65 {
66 try
67 {
68 int temp;
69 //if expression does not throw an exception when evaluated at "1", we assume it to be valid
70 EvaluateInternal(1, 0, out temp);
71 this.isValid = true;
72 }
73 catch (FormatException)
74 {
75 this.isValid = false;
76 }
77 catch (System.Collections.Generic.KeyNotFoundException)
78 {
79 this.isValid = false;
80 }
81
82 }
83
84 static bool IsOperator(char character)
85 {
86 if (character == '+' || character == '-' || character == '*'
87 || character == '/' || character == '^' || character == '%')
88 return true;
89 return false;
90
91 }
92
93 public double EvaluateInternal(double dvalueX, int startIndex, out int endIndex)
94 {
95 //exceptions are bubbled up
96
97 //dAnswer is the running total
98 double dAnswer = 0, dOperand = 0;
99 char chCurrentChar, chOperator = '+';
100 string strAngleOperator;
101
102 for (int i = startIndex + 1; i < textInternal.Length; i++)
103 {
104 startIndex = i;
105 chCurrentChar = textInternal[startIndex];
106
107 // if found a number, update dOperand
108 if (char.IsDigit(chCurrentChar))
109 {
110 while (char.IsDigit(textInternal[i]) || textInternal[i] == '.')
111 i++;
112 dOperand = Convert.ToDouble(textInternal.Substring(startIndex, i - startIndex));
113 i--;
114 }
115 //if found an operator
116 else if (IsOperator(chCurrentChar))
117 {
118 dAnswer = DoOperation(dAnswer, dOperand, chOperator);
119 chOperator = chCurrentChar;
120 }
121 //if found independent variable
122 else if (char.ToLower(chCurrentChar) == charX)
123 {
124 dOperand = dvalueX;
125 }
126 //if found a bracket, solve it first
127 else if (chCurrentChar == '(')
128 {
129 dOperand = EvaluateInternal(dvalueX, i, out endIndex);
130 i = endIndex;
131 }
132 //if found closing bracket, return result
133 else if (chCurrentChar == ')')
134 {
135 dAnswer = DoOperation(dAnswer, dOperand, chOperator);
136 endIndex = i;
137 return dAnswer;
138 }
139
140 else //could be any function e.g. "sin" or any constant e.g "pi"
141 {
142 while (char.IsLetter(textInternal[i]))
143 i++;
144 //if we got letters followed by "(", we've got a function else a constant
145 if (textInternal[i] == '(')
146 {
147 strAngleOperator = textInternal.Substring(startIndex, i - startIndex).ToLower();
148 dOperand = EvaluateInternal(dvalueX, i, out endIndex);
149 i = endIndex;
150 dOperand = DoAngleOperation(dOperand, strAngleOperator);
151 }
152 else //constant
153 {
154 dOperand = this.constants[textInternal.Substring(startIndex, i - startIndex).ToLower()];
155 i--;
156 }
157 }
158 if (double.IsNaN(dAnswer) || double.IsNaN(dOperand))
159 {
160 endIndex = i;
161 return double.NaN;
162 }
163 }
164 endIndex = textInternal.Length;
165 return 0;
166 }
167
168 //this function contains definitions for supported functions, we can add more also.
169 static double DoAngleOperation(double dOperand, string strOperator)
170 {
171 const double pi = 3.1415926535897932384626433832795;
172 strOperator = strOperator.ToLower();
173 switch (strOperator)
174 {
175 case "abs":
176 if (ExpressionHelper.BlnRadian)
177 {
178 return Math.Abs(dOperand);
179 }
180 else
181 {
182 return Math.Abs(dOperand*pi/180);
183 }
184 case "sin":
185 if (ExpressionHelper.BlnRadian)
186 {
187 return Math.Sin(dOperand);
188 }
189 else
190 {
191 return Math.Sin(dOperand*pi/180);
192 }
193 case "cos":
194 if (ExpressionHelper.BlnRadian)
195 {
196 return Math.Cos(dOperand);
197 }
198 else
199 {
200 return Math.Cos(dOperand*pi/180);
201 }
202 case "tan":
203 if (ExpressionHelper.BlnRadian)
204 {
205 return Math.Tan(dOperand);
206 }
207 else
208 {
209 return Math.Tan(dOperand*pi/180);
210 }
211 case "sec":
212 if (ExpressionHelper.BlnRadian)
213 {
214 return 1.0 / Math.Cos(dOperand);
215 }
216 else
217 {
218 return 1.0 / Math.Cos(dOperand*pi/180);
219 }
220 case "cosec":
221 if (ExpressionHelper.BlnRadian)
222 {
223 return 1.0 / Math.Sin(dOperand);
224 }
225 else
226 {
227 return 1.0 / Math.Sin(dOperand*pi/180);
228 }
229 case "cot":
230 if (ExpressionHelper.BlnRadian)
231 {
232 return 1.0 / Math.Tan(dOperand);
233 }
234 else
235 {
236 return 1.0 / Math.Tan(dOperand*pi/180);
237 }
238 case "arcsin":
239 if (ExpressionHelper.BlnRadian)
240 {
241 return Math.Asin(dOperand);
242 }
243 else
244 {
245 return Math.Asin(dOperand*pi/180);
246 }
247 case "arccos":
248 if (ExpressionHelper.BlnRadian)
249 {
250 return Math.Acos(dOperand);
251 }
252 else
253 {
254 return Math.Acos(dOperand*pi/180);
255 }
256 case "arctan":
257 if (ExpressionHelper.BlnRadian)
258 {
259 return Math.Atan(dOperand);
260 }
261 else
262 {
263 return Math.Atan(dOperand*pi/180);
264 }
265 case "exp":
266 if (ExpressionHelper.BlnRadian)
267 {
268 return Math.Exp(dOperand);
269 }
270 else
271 {
272 return Math.Exp(dOperand*pi/180);
273 }
274 case "ln":
275 if (ExpressionHelper.BlnRadian)
276 {
277 return Math.Log(dOperand);
278 }
279 else
280 {
281 return Math.Log(dOperand*pi/180);
282 }
283 case "log":
284 if (ExpressionHelper.BlnRadian)
285 {
286 return Math.Log10(dOperand);
287 }
288 else
289 {
290 return Math.Log10(dOperand*pi/180);
291 }
292 case "antilog":
293 if (ExpressionHelper.BlnRadian)
294 {
295 return Math.Pow(10, dOperand);
296 }
297 else
298 {
299 return Math.Pow(10, dOperand)*pi/180;
300 }
301 case "sqrt":
302 if (ExpressionHelper.BlnRadian)
303 {
304 return Math.Sqrt(dOperand);
305 }
306 else
307 {
308 return Math.Sqrt(dOperand*pi/180);
309 }
310
311 case "sinh":
312 if (ExpressionHelper.BlnRadian)
313 {
314 return Math.Sinh(dOperand);
315 }
316 else
317 {
318 return Math.Sinh(dOperand*pi/180);
319 }
320 case "cosh":
321 if (ExpressionHelper.BlnRadian)
322 {
323 return Math.Cosh(dOperand);
324 }
325 else
326 {
327 return Math.Cosh(dOperand*pi/180);
328 }
329 case "tanh":
330 if (ExpressionHelper.BlnRadian)
331 {
332 return Math.Tanh(dOperand);
333 }
334 else
335 {
336 return Math.Tanh(dOperand*pi/180);
337 }
338 case "arcsinh":
339 if (ExpressionHelper.BlnRadian)
340 {
341 return Math.Log(dOperand + Math.Sqrt(dOperand * dOperand + 1));
342 }
343 else
344 {
345 return Math.Log(dOperand + Math.Sqrt((dOperand * dOperand + 1)*pi/180));
346 }
347 case "arccosh":
348 if (ExpressionHelper.BlnRadian)
349 {
350 return Math.Log(dOperand + Math.Sqrt(dOperand * dOperand - 1));
351 }
352 else
353 {
354 return Math.Log(dOperand + Math.Sqrt((dOperand * dOperand - 1)*pi/180));
355 }
356 case "arctanh":
357 if (ExpressionHelper.BlnRadian)
358 {
359 return Math.Log((1 + dOperand) / (1 - dOperand)) / 2;
360 }
361 else
362 {
363 return Math.Log(((1 + dOperand) / (1 - dOperand)) * pi / 180) / 2;
364 }
365 default:
366 //throw new ArgumentException("InvalidAngleOperatorException");
367 return double.NaN;
368 }
369 }
370
371 // returns dOperant1 (op) dOperand2
372 static double DoOperation(double dOperand1, double dOperand2, char chOperator)
373 {
374 switch (chOperator)
375 {
376 case '+':
377 return dOperand1 + dOperand2;
378 case '-':
379 return dOperand1 - dOperand2;
380 case '*':
381 return dOperand1 * dOperand2;
382 case '/':
383 return dOperand1 / dOperand2;
384 case '^':
385 return Math.Pow(dOperand1, dOperand2);
386 case '%':
387 return dOperand1 % dOperand2;
388 }
389 return double.NaN;
390 }
391
392 //insert brackets at appropriate positions since the evaluation function
393 // only evaluates from Left To Right considering only bracket's precedence
394 string InsertPrecedenceBrackets()
395 {
396 int i = 0, j = 0;
397 int iBrackets = 0;
398 bool bReplace = false;
399 int iLengthExpression;
400 string strExpression = this.textInternal;
401
402 //Precedence for * && /
403 i = 1;
404 iLengthExpression = strExpression.Length;
405 while (i <= iLengthExpression)
406 {
407 if (strExpression.Substring(-1 + i, 1) == "*" || strExpression.Substring(-1 + i, 1) == "/")
408 {
409 for (j = i - 1; j > 0; j--)
410 {
411 if (strExpression.Substring(-1 + j, 1) == ")")
412 iBrackets = iBrackets + 1;
413 if (strExpression.Substring(-1 + j, 1) == "(")
414 iBrackets = iBrackets - 1;
415 if (iBrackets < 0)
416 break;
417 if (iBrackets == 0)
418 {
419 if (strExpression.Substring(-1 + j, 1) == "+" || strExpression.Substring(-1 + j, 1) == "-")
420 {
421 strExpression = strExpression.Substring(-1 + 1, j) + "(" + strExpression.Substring(-1 + j + 1);
422 bReplace = true;
423 i = i + 1;
424 break;
425 }
426 }
427 }
428 iBrackets = 0;
429 j = i;
430 i = i + 1;
431 while (bReplace == true)
432 {
433 j = j + 1;
434 if (strExpression.Substring(-1 + j, 1) == "(")
435 iBrackets = iBrackets + 1;
436 if (strExpression.Substring(-1 + j, 1) == ")")
437 {
438 if (iBrackets == 0)
439 {
440 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
441 bReplace = false;
442 i = i + 1;
443 break;
444 }
445 else
446 iBrackets = iBrackets - 1;
447 }
448 if (strExpression.Substring(-1 + j, 1) == "+" || strExpression.Substring(-1 + j, 1) == "-")
449 {
450 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
451 bReplace = false;
452 i = i + 1;
453 break;
454 }
455 }
456 }
457
458 iLengthExpression = strExpression.Length;
459 i = i + 1;
460 }
461
462
463 //Precedence for ^ && %
464 i = 1;
465 iLengthExpression = strExpression.Length;
466 while (i <= iLengthExpression)
467 {
468 if (strExpression.Substring(-1 + i, 1) == "^" || strExpression.Substring(-1 + i, 1) == "%")
469 {
470 for (j = i - 1; j > 0; j--)
471 {
472 if (strExpression.Substring(-1 + j, 1) == ")")
473 iBrackets = iBrackets + 1;
474 if (strExpression.Substring(-1 + j, 1) == "(")
475 iBrackets = iBrackets - 1;
476 if (iBrackets < 0)
477 break;
478 if (iBrackets == 0)
479 {
480 if (strExpression.Substring(-1 + j, 1) == "+"
481 || strExpression.Substring(-1 + j, 1) == "-"
482 || strExpression.Substring(-1 + j, 1) == "*"
483 || strExpression.Substring(-1 + j, 1) == "/")
484 {
485 strExpression = strExpression.Substring(-1 + 1, j) + "(" + strExpression.Substring(-1 + j + 1);
486 bReplace = true;
487 i = i + 1;
488 break;
489 }
490 }
491 }
492 iBrackets = 0;
493 j = i;
494 i = i + 1;
495 while (bReplace == true)
496 {
497 j = j + 1;
498 if (strExpression.Substring(-1 + j, 1) == "(")
499 iBrackets = iBrackets + 1;
500 if (strExpression.Substring(-1 + j, 1) == ")")
501 {
502 if (iBrackets == 0)
503 {
504 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
505 bReplace = false;
506 i = i + 1;
507 break;
508 }
509 else
510 iBrackets = iBrackets - 1;
511 }
512 if (strExpression.Substring(-1 + j, 1) == "+" || strExpression.Substring(-1 + j, 1) == "-"
513 || strExpression.Substring(-1 + j, 1) == "*" || strExpression.Substring(-1 + j, 1) == "/")
514 {
515 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
516 bReplace = false;
517 i = i + 1;
518 break;
519 }
520 }
521 }
522 iLengthExpression = strExpression.Length;
523 i = i + 1;
524 }
525 return strExpression;
526 }
527
528 static double GetR(double X, double Y)
529 {
530 return Math.Sqrt(X * X + Y * Y);
531 }
532
533 static double GetTheta(double X, double Y)
534 {
535 double dTheta;
536 if (X == 0)
537 {
538 if (Y > 0)
539 dTheta = Math.PI / 2;
540 else
541 dTheta = -Math.PI / 2;
542 }
543 else
544 dTheta = Math.Atan(Y / X);
545
546 //actual range of theta is from 0 to 2PI
547 if (X < 0)
548 dTheta = dTheta + Math.PI;
549 else if (Y < 0)
550 dTheta = dTheta + 2 * Math.PI;
551 return dTheta;
552 }
553
554 #endregion
555
556 }
557 }
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace VietGraph
6 {
7 public class Expression : IEvaluatable
8 {
9 string text = "";
10 string textInternal = "";
11 bool isValid = false;
12 char charX = 'x';
13 System.Collections.Generic.Dictionary<string, double> constants;
14
15 public Expression(string expressionText)
16 {
17 this.constants = new Dictionary<string, double>();
18 this.constants.Add("pi", Math.PI);
19 this.constants.Add("e", Math.E);
20 this.ExpressionText = expressionText;
21 }
22
23 #region Public Properties for IEvaluatable
24
25
26 public string ExpressionText
27 {
28 get
29 {
30 return this.text;
31 }
32 set
33 {
34 this.text = value;
35 this.textInternal = "(" + value + ")";
36 this.textInternal = InsertPrecedenceBrackets().Trim();
37 this.Validate();
38 }
39 }
40
41 public bool IsValid
42 {
43 get
44 {
45 return this.isValid;
46 }
47 }
48 #endregion
49
50 #region Public Methods for IEvaluatable
51
52 public double Evaluate(double dvalueX)
53 {
54 if (this.isValid == false)
55 return Double.NaN;
56 int temp;
57 return EvaluateInternal(dvalueX, 0, out temp);
58 }
59
60 #endregion
61
62 #region Private Methods
63
64 private void Validate()
65 {
66 try
67 {
68 int temp;
69 //if expression does not throw an exception when evaluated at "1", we assume it to be valid
70 EvaluateInternal(1, 0, out temp);
71 this.isValid = true;
72 }
73 catch (FormatException)
74 {
75 this.isValid = false;
76 }
77 catch (System.Collections.Generic.KeyNotFoundException)
78 {
79 this.isValid = false;
80 }
81
82 }
83
84 static bool IsOperator(char character)
85 {
86 if (character == '+' || character == '-' || character == '*'
87 || character == '/' || character == '^' || character == '%')
88 return true;
89 return false;
90
91 }
92
93 public double EvaluateInternal(double dvalueX, int startIndex, out int endIndex)
94 {
95 //exceptions are bubbled up
96
97 //dAnswer is the running total
98 double dAnswer = 0, dOperand = 0;
99 char chCurrentChar, chOperator = '+';
100 string strAngleOperator;
101
102 for (int i = startIndex + 1; i < textInternal.Length; i++)
103 {
104 startIndex = i;
105 chCurrentChar = textInternal[startIndex];
106
107 // if found a number, update dOperand
108 if (char.IsDigit(chCurrentChar))
109 {
110 while (char.IsDigit(textInternal[i]) || textInternal[i] == '.')
111 i++;
112 dOperand = Convert.ToDouble(textInternal.Substring(startIndex, i - startIndex));
113 i--;
114 }
115 //if found an operator
116 else if (IsOperator(chCurrentChar))
117 {
118 dAnswer = DoOperation(dAnswer, dOperand, chOperator);
119 chOperator = chCurrentChar;
120 }
121 //if found independent variable
122 else if (char.ToLower(chCurrentChar) == charX)
123 {
124 dOperand = dvalueX;
125 }
126 //if found a bracket, solve it first
127 else if (chCurrentChar == '(')
128 {
129 dOperand = EvaluateInternal(dvalueX, i, out endIndex);
130 i = endIndex;
131 }
132 //if found closing bracket, return result
133 else if (chCurrentChar == ')')
134 {
135 dAnswer = DoOperation(dAnswer, dOperand, chOperator);
136 endIndex = i;
137 return dAnswer;
138 }
139
140 else //could be any function e.g. "sin" or any constant e.g "pi"
141 {
142 while (char.IsLetter(textInternal[i]))
143 i++;
144 //if we got letters followed by "(", we've got a function else a constant
145 if (textInternal[i] == '(')
146 {
147 strAngleOperator = textInternal.Substring(startIndex, i - startIndex).ToLower();
148 dOperand = EvaluateInternal(dvalueX, i, out endIndex);
149 i = endIndex;
150 dOperand = DoAngleOperation(dOperand, strAngleOperator);
151 }
152 else //constant
153 {
154 dOperand = this.constants[textInternal.Substring(startIndex, i - startIndex).ToLower()];
155 i--;
156 }
157 }
158 if (double.IsNaN(dAnswer) || double.IsNaN(dOperand))
159 {
160 endIndex = i;
161 return double.NaN;
162 }
163 }
164 endIndex = textInternal.Length;
165 return 0;
166 }
167
168 //this function contains definitions for supported functions, we can add more also.
169 static double DoAngleOperation(double dOperand, string strOperator)
170 {
171 const double pi = 3.1415926535897932384626433832795;
172 strOperator = strOperator.ToLower();
173 switch (strOperator)
174 {
175 case "abs":
176 if (ExpressionHelper.BlnRadian)
177 {
178 return Math.Abs(dOperand);
179 }
180 else
181 {
182 return Math.Abs(dOperand*pi/180);
183 }
184 case "sin":
185 if (ExpressionHelper.BlnRadian)
186 {
187 return Math.Sin(dOperand);
188 }
189 else
190 {
191 return Math.Sin(dOperand*pi/180);
192 }
193 case "cos":
194 if (ExpressionHelper.BlnRadian)
195 {
196 return Math.Cos(dOperand);
197 }
198 else
199 {
200 return Math.Cos(dOperand*pi/180);
201 }
202 case "tan":
203 if (ExpressionHelper.BlnRadian)
204 {
205 return Math.Tan(dOperand);
206 }
207 else
208 {
209 return Math.Tan(dOperand*pi/180);
210 }
211 case "sec":
212 if (ExpressionHelper.BlnRadian)
213 {
214 return 1.0 / Math.Cos(dOperand);
215 }
216 else
217 {
218 return 1.0 / Math.Cos(dOperand*pi/180);
219 }
220 case "cosec":
221 if (ExpressionHelper.BlnRadian)
222 {
223 return 1.0 / Math.Sin(dOperand);
224 }
225 else
226 {
227 return 1.0 / Math.Sin(dOperand*pi/180);
228 }
229 case "cot":
230 if (ExpressionHelper.BlnRadian)
231 {
232 return 1.0 / Math.Tan(dOperand);
233 }
234 else
235 {
236 return 1.0 / Math.Tan(dOperand*pi/180);
237 }
238 case "arcsin":
239 if (ExpressionHelper.BlnRadian)
240 {
241 return Math.Asin(dOperand);
242 }
243 else
244 {
245 return Math.Asin(dOperand*pi/180);
246 }
247 case "arccos":
248 if (ExpressionHelper.BlnRadian)
249 {
250 return Math.Acos(dOperand);
251 }
252 else
253 {
254 return Math.Acos(dOperand*pi/180);
255 }
256 case "arctan":
257 if (ExpressionHelper.BlnRadian)
258 {
259 return Math.Atan(dOperand);
260 }
261 else
262 {
263 return Math.Atan(dOperand*pi/180);
264 }
265 case "exp":
266 if (ExpressionHelper.BlnRadian)
267 {
268 return Math.Exp(dOperand);
269 }
270 else
271 {
272 return Math.Exp(dOperand*pi/180);
273 }
274 case "ln":
275 if (ExpressionHelper.BlnRadian)
276 {
277 return Math.Log(dOperand);
278 }
279 else
280 {
281 return Math.Log(dOperand*pi/180);
282 }
283 case "log":
284 if (ExpressionHelper.BlnRadian)
285 {
286 return Math.Log10(dOperand);
287 }
288 else
289 {
290 return Math.Log10(dOperand*pi/180);
291 }
292 case "antilog":
293 if (ExpressionHelper.BlnRadian)
294 {
295 return Math.Pow(10, dOperand);
296 }
297 else
298 {
299 return Math.Pow(10, dOperand)*pi/180;
300 }
301 case "sqrt":
302 if (ExpressionHelper.BlnRadian)
303 {
304 return Math.Sqrt(dOperand);
305 }
306 else
307 {
308 return Math.Sqrt(dOperand*pi/180);
309 }
310
311 case "sinh":
312 if (ExpressionHelper.BlnRadian)
313 {
314 return Math.Sinh(dOperand);
315 }
316 else
317 {
318 return Math.Sinh(dOperand*pi/180);
319 }
320 case "cosh":
321 if (ExpressionHelper.BlnRadian)
322 {
323 return Math.Cosh(dOperand);
324 }
325 else
326 {
327 return Math.Cosh(dOperand*pi/180);
328 }
329 case "tanh":
330 if (ExpressionHelper.BlnRadian)
331 {
332 return Math.Tanh(dOperand);
333 }
334 else
335 {
336 return Math.Tanh(dOperand*pi/180);
337 }
338 case "arcsinh":
339 if (ExpressionHelper.BlnRadian)
340 {
341 return Math.Log(dOperand + Math.Sqrt(dOperand * dOperand + 1));
342 }
343 else
344 {
345 return Math.Log(dOperand + Math.Sqrt((dOperand * dOperand + 1)*pi/180));
346 }
347 case "arccosh":
348 if (ExpressionHelper.BlnRadian)
349 {
350 return Math.Log(dOperand + Math.Sqrt(dOperand * dOperand - 1));
351 }
352 else
353 {
354 return Math.Log(dOperand + Math.Sqrt((dOperand * dOperand - 1)*pi/180));
355 }
356 case "arctanh":
357 if (ExpressionHelper.BlnRadian)
358 {
359 return Math.Log((1 + dOperand) / (1 - dOperand)) / 2;
360 }
361 else
362 {
363 return Math.Log(((1 + dOperand) / (1 - dOperand)) * pi / 180) / 2;
364 }
365 default:
366 //throw new ArgumentException("InvalidAngleOperatorException");
367 return double.NaN;
368 }
369 }
370
371 // returns dOperant1 (op) dOperand2
372 static double DoOperation(double dOperand1, double dOperand2, char chOperator)
373 {
374 switch (chOperator)
375 {
376 case '+':
377 return dOperand1 + dOperand2;
378 case '-':
379 return dOperand1 - dOperand2;
380 case '*':
381 return dOperand1 * dOperand2;
382 case '/':
383 return dOperand1 / dOperand2;
384 case '^':
385 return Math.Pow(dOperand1, dOperand2);
386 case '%':
387 return dOperand1 % dOperand2;
388 }
389 return double.NaN;
390 }
391
392 //insert brackets at appropriate positions since the evaluation function
393 // only evaluates from Left To Right considering only bracket's precedence
394 string InsertPrecedenceBrackets()
395 {
396 int i = 0, j = 0;
397 int iBrackets = 0;
398 bool bReplace = false;
399 int iLengthExpression;
400 string strExpression = this.textInternal;
401
402 //Precedence for * && /
403 i = 1;
404 iLengthExpression = strExpression.Length;
405 while (i <= iLengthExpression)
406 {
407 if (strExpression.Substring(-1 + i, 1) == "*" || strExpression.Substring(-1 + i, 1) == "/")
408 {
409 for (j = i - 1; j > 0; j--)
410 {
411 if (strExpression.Substring(-1 + j, 1) == ")")
412 iBrackets = iBrackets + 1;
413 if (strExpression.Substring(-1 + j, 1) == "(")
414 iBrackets = iBrackets - 1;
415 if (iBrackets < 0)
416 break;
417 if (iBrackets == 0)
418 {
419 if (strExpression.Substring(-1 + j, 1) == "+" || strExpression.Substring(-1 + j, 1) == "-")
420 {
421 strExpression = strExpression.Substring(-1 + 1, j) + "(" + strExpression.Substring(-1 + j + 1);
422 bReplace = true;
423 i = i + 1;
424 break;
425 }
426 }
427 }
428 iBrackets = 0;
429 j = i;
430 i = i + 1;
431 while (bReplace == true)
432 {
433 j = j + 1;
434 if (strExpression.Substring(-1 + j, 1) == "(")
435 iBrackets = iBrackets + 1;
436 if (strExpression.Substring(-1 + j, 1) == ")")
437 {
438 if (iBrackets == 0)
439 {
440 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
441 bReplace = false;
442 i = i + 1;
443 break;
444 }
445 else
446 iBrackets = iBrackets - 1;
447 }
448 if (strExpression.Substring(-1 + j, 1) == "+" || strExpression.Substring(-1 + j, 1) == "-")
449 {
450 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
451 bReplace = false;
452 i = i + 1;
453 break;
454 }
455 }
456 }
457
458 iLengthExpression = strExpression.Length;
459 i = i + 1;
460 }
461
462
463 //Precedence for ^ && %
464 i = 1;
465 iLengthExpression = strExpression.Length;
466 while (i <= iLengthExpression)
467 {
468 if (strExpression.Substring(-1 + i, 1) == "^" || strExpression.Substring(-1 + i, 1) == "%")
469 {
470 for (j = i - 1; j > 0; j--)
471 {
472 if (strExpression.Substring(-1 + j, 1) == ")")
473 iBrackets = iBrackets + 1;
474 if (strExpression.Substring(-1 + j, 1) == "(")
475 iBrackets = iBrackets - 1;
476 if (iBrackets < 0)
477 break;
478 if (iBrackets == 0)
479 {
480 if (strExpression.Substring(-1 + j, 1) == "+"
481 || strExpression.Substring(-1 + j, 1) == "-"
482 || strExpression.Substring(-1 + j, 1) == "*"
483 || strExpression.Substring(-1 + j, 1) == "/")
484 {
485 strExpression = strExpression.Substring(-1 + 1, j) + "(" + strExpression.Substring(-1 + j + 1);
486 bReplace = true;
487 i = i + 1;
488 break;
489 }
490 }
491 }
492 iBrackets = 0;
493 j = i;
494 i = i + 1;
495 while (bReplace == true)
496 {
497 j = j + 1;
498 if (strExpression.Substring(-1 + j, 1) == "(")
499 iBrackets = iBrackets + 1;
500 if (strExpression.Substring(-1 + j, 1) == ")")
501 {
502 if (iBrackets == 0)
503 {
504 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
505 bReplace = false;
506 i = i + 1;
507 break;
508 }
509 else
510 iBrackets = iBrackets - 1;
511 }
512 if (strExpression.Substring(-1 + j, 1) == "+" || strExpression.Substring(-1 + j, 1) == "-"
513 || strExpression.Substring(-1 + j, 1) == "*" || strExpression.Substring(-1 + j, 1) == "/")
514 {
515 strExpression = strExpression.Substring(-1 + 1, j - 1) + ")" + strExpression.Substring(-1 + j);
516 bReplace = false;
517 i = i + 1;
518 break;
519 }
520 }
521 }
522 iLengthExpression = strExpression.Length;
523 i = i + 1;
524 }
525 return strExpression;
526 }
527
528 static double GetR(double X, double Y)
529 {
530 return Math.Sqrt(X * X + Y * Y);
531 }
532
533 static double GetTheta(double X, double Y)
534 {
535 double dTheta;
536 if (X == 0)
537 {
538 if (Y > 0)
539 dTheta = Math.PI / 2;
540 else
541 dTheta = -Math.PI / 2;
542 }
543 else
544 dTheta = Math.Atan(Y / X);
545
546 //actual range of theta is from 0 to 2PI
547 if (X < 0)
548 dTheta = dTheta + Math.PI;
549 else if (Y < 0)
550 dTheta = dTheta + 2 * Math.PI;
551 return dTheta;
552 }
553
554 #endregion
555
556 }
557 }